package Serveur;

import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.Iterator;

import Both.Reservation;
import Both.Trajet;
import Both.Transport;
import Both.Ville;
import Client.DemandeRechercheClient;
import ClientAdmin.DemandeModificationTrajet;
import ClientAdmin.DemandeModificationTransport;

/**
 * Classe charg� de serialiser les transport et les rajets;
 * 
 * @author user
 * 
 */
public class Serveur {

    private static boolean singleton = false;

    private ArrayList<Transport> ListeTransport;
    private ArrayList<Trajet> ListeTrajet;
    private ArrayList<Reservation> ListeReservations;

    private Serialization Files;

    /**
     * Construteur normal
     */
    public Serveur() {
        if (!singleton) {
            singleton = true;
            Files = new Serialization();

            ListeTransport = Files.fillOutListeTransport();
            ListeTrajet = Files.fillOutListeTrajet();
            ListeReservations = Files.fillOutListeReservation();
        } else {
            System.out.println("Un serveur existe d�j�");
        }
    }

    /**
     * Accesseur de consultation de la liste des transports
     * 
     * @return
     */
    public ArrayList<Transport> getListeTransport() {
        return ListeTransport;
    }

    /**
     * Accesseur de consultation de la liste des Reservations
     * 
     * @return
     */
    public ArrayList<Reservation> getListeReservations() {
        return ListeReservations;
    }

    /**
     * Accesseur de consultation de la liste des Trajet
     * 
     * @return
     */
    public ArrayList<Trajet> getListeTrajet() {
        return ListeTrajet;
    }

    /**
     * Afficher tous les transport
     */
    public void displayAllTransport() {
        Iterator<Transport> it = ListeTransport.iterator();

        while (it.hasNext()) {
            Transport t = (Transport) it.next();
            t.print();
        }
    }

    /**
     * Afficher la liste des trajets
     */
    public void displayAllTrajet() {
        Iterator<Trajet> it = ListeTrajet.iterator();

        while (it.hasNext()) {
            Trajet t = (Trajet) it.next();
            t.print();
        }
    }

    /**
     * Afficher toutes les reservations
     */
    public void displayAllReservations() {
        Iterator<Reservation> it = ListeReservations.iterator();

        while (it.hasNext()) {
            Reservation res = (Reservation) it.next();
            res.print();
        }
    }

    /**
     * Fermer le serveur en serialisant les listes
     */
    public void closeServeur() {
        singleton = false;
        Files.close(ListeTransport, ListeTrajet, ListeReservations);
    }

    public ArrayList<Transport> searchTransport(String nom) {
        return Transport.searchTransport(ListeTransport, nom);
    }

    public void addReservation(Reservation R) {
        ListeReservations.add(R);
    }

    public boolean analyserDemandeReservation(Reservation R) {
        return R.Reserver(this);
    }

    /**
     * Methode permettant d'analyser une commande pass�e par un client grace �
     * l'objet Reservation
     * 
     * @param rech
     * @return
     */
    public ArrayList<Trajet> analyserDemandeRecherche(
            DemandeRechercheClient rech) {
        return Trajet.searchTrajet(ListeTrajet, rech.getVilledep(), rech
                .getVilleArr(), rech.getDateDep(), rech.getDateArr(), rech
                .getTrans(), rech.getNbPlace());
    }

    /**
     * Methode permettant de tester la methode
     */
    public void viderListes() {
        ListeReservations.clear();
        ListeTrajet.clear();
        ListeTransport.clear();
    }

    /**
     * Modifier un transport
     * 
     * @param t
     * @param i
     */
    public boolean setTransport(Transport t, String nom, int numTrans,
            String description, int capacite) {
        ArrayList<Transport> ListeTransport = getListeTransport();
        int indexMod = ListeTransport.indexOf(t);

        // Verifier que le transport existe dans le serveur
        if (indexMod == -1) {
            return false;
        }

        // Verifier tous les champs
        String nom2 = nom;
        int numTrans2 = numTrans;
        String description2 = description;
        int capacite2 = capacite;

        if (nom == null) {
            nom2 = t.getNom();
        }
        if (numTrans == 0) {
            numTrans2 = t.getNumTrans();
        }
        if (description == null) {
            description2 = t.getDescription();
        }
        if (capacite == 0) {
            capacite2 = t.getCapacite();
        }

        // verifier si les champs contiennent un /
        nom2.replace(Serialization.CAR_SPACE, Serialization.CAR_REPLACE);
        description2
                .replace(Serialization.CAR_SPACE, Serialization.CAR_REPLACE);

        // Creer le nouvelle objet transport
        Transport tNew = new Transport(nom2, description2, numTrans2, capacite2);

        // Modifier l'objet dans la liste
        ListeTransport.set(indexMod, tNew);

        return true;
    }

    /**
     * Modifier un transport
     * 
     * @param t
     * @param i
     */
    public boolean setTransport(Transport old, Transport newTrans) {
        // Recuperer l'emplacement du transport dans la liste
        int index = getIndexOfTransport(old);

        try {
            getListeTransport().set(index, newTrans);
        } catch (Exception e) {
            return false;
        }

        return true;
    }

    /**
     * Modifier un transport
     * 
     * @param t
     * @param i
     */
    public boolean setTrajet(Trajet oldtraj, GregorianCalendar dateDep,
            GregorianCalendar dateArr, Ville villeDep, Ville villeArr,
            int placeOcc, Transport trans) {
        ArrayList<Trajet> listeTrajets = getListeTrajet();
        int indexMod = listeTrajets.indexOf(oldtraj);

        // Verifier que le transport existe dans le serveur
        if (indexMod == -1) {
            return false;
        }

        // Verifier tous les champs
        GregorianCalendar dateDep2 = dateDep;
        GregorianCalendar dateArr2 = dateArr;
        Ville villeDep2 = villeDep;
        Ville villeArr2 = villeArr;
        int placeOcc2 = placeOcc;
        Transport trans2 = trans;

        if (dateDep == null) {
            dateDep2 = oldtraj.getDatedepart();
        }

        if (dateArr == null) {
            dateArr2 = oldtraj.getDatearrive();
        }

        if (villeDep == null) {
            villeDep2 = oldtraj.getVilleDepart();
        }

        if (villeArr == null) {
            villeArr2 = oldtraj.getVilleArrive();
        }

        if (trans == null) {
            trans2 = oldtraj.getTransport();
        }

        if (placeOcc == 0) {
            placeOcc2 = oldtraj.getPlaceOcupper();
        }

        // Creer le nouvelle objet transport
        Trajet newTraj = new Trajet(villeDep2, villeArr2, dateDep2, dateArr2,
                trans2);

        // Modifier l'objet dans la liste
        listeTrajets.set(indexMod, newTraj);

        return true;
    }

    /**
     * Modifier un transport
     * 
     * @param t
     * @param i
     */
    public boolean setTrajet(Trajet old, Trajet newTrans) {
        // Recuperer l'emplacement du transport dans la liste
        int index = getIndexOfTrajet(old);

        try {
            getListeTrajet().set(index, newTrans);
        } catch (Exception e) {
            return false;
        }

        return true;
    }

    /**
     * Recuperer l'index d'un transport
     */
    public int getIndexOfTransport(Transport t) {
        return getListeTransport().indexOf(t);
    }

    /**
     * Recuperer l'index d'un trajet
     */
    public int getIndexOfTrajet(Trajet t) {
        return getListeTrajet().indexOf(t);
    }

    /**
     * Ajouter un transport dans la liste
     * 
     * @param m
     */
    public void addTransport(Transport m) {
        // Verifier que le transport n'est pas d�j� present
        if (getListeTransport().contains(m)) {
            System.out.println("L'objet existe d�ja dans la liste");
            return;
        }
        // ajouter le tansport
        if (!getListeTransport().add(m)) {
            System.out.println("Impossible d'ajouter l'objet");
            return;
        }
    }

    /**
     * Modifier un transport avec les parametres donn�es
     * 
     * @param dem
     * @return
     */
    public boolean analyserDemandeModificationTransportAdmin(
            DemandeModificationTransport dem) {
        if (dem.getCapacite() == 0 && dem.getDescription() == null
                && dem.getNom() == null && dem.getNum() == 0
                && dem.getOldTrans() == null && dem.getNewTrans() != null) {
            addTransport(dem.getNewTrans());
            return true;
        }

        // Modification d'un transport avec les parametres
        if (dem.getNewTrans() != null && dem.getOldTrans() == null) {
            return setTransport(dem.getNewTrans(), dem.getNom(), dem.getNum(),
                    dem.getDescription(), dem.getCapacite());
        }

        // remplacement d'un transport par un autre
        if (dem.getCapacite() == 0 && dem.getDescription() == null
                && dem.getNom() == null && dem.getNum() == 0
                && dem.getNewTrans() != null && dem.getOldTrans() != null) {
            return setTransport(dem.getOldTrans(), dem.getNewTrans());
        }

        return false;
    }

    /**
     * Modifier un transport avec les parametres donn�es
     * 
     * @param dem
     * @return
     */
    public boolean analyserDemandeModificationTrajetAdmin(
            DemandeModificationTrajet dem) {
        if (dem.getVilleDepart() == null && dem.getVilleArrive() == null
                && dem.getTrans() == null && dem.getPlaceOccuper() == 0
                && dem.getOld() == null && dem.getDateDepart() == null
                && dem.getDateArrive() == null && dem.getNewtraj() != null) {
            return addTrajet(dem.getNewtraj());
        }

        // Modification d'un transport avec les parametres
        if (dem.getNewtraj() != null && dem.getOld() != null) {
            return setTrajet(dem.getOld(), dem.getNewtraj());
        }

        // remplacement d'un transport par un autre
        if (dem.getNewtraj() == null) {
            return setTrajet(dem.getOld(), dem.getDateDepart(), dem
                    .getDateArrive(), dem.getVilleDepart(), dem
                    .getVilleArrive(), dem.getPlaceOccuper(), dem.getTrans());
        }

        return false;
    }

    /**
     * Ajouter un trajet dans la liste
     * 
     * @param m
     */
    public boolean addTrajet(Trajet m) {
        // Verifier si le trajet est present dans la liste
        if (getListeTrajet().contains(m)) {
            System.out.println("L'objet existe d�ja dans la liste");
            return true;
        }

        // Ajouter le trajet � la liste
        if (!getListeTrajet().add(m)) {
            System.out.println("Impossible d'ajouter l'objet");
            return true;
        }

        return false;
    }

    /**
     * Supprimer un transport
     * 
     * @param m
     */
    public boolean removeTransport(Transport m) {
        if (!getListeTransport().remove(m)) {
            return false;
        }
        return true;
    }

    /**
     * Supprimer un transport
     * 
     * @param m
     */
    public void removeTrajet(Trajet t) {
        if (!getListeTrajet().remove(t)) {
            System.out.println("Impossible d'enlever l'objet");
        }
    }
}
